package tt.dz.biz.service.batchpay;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.Resource;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service;
import tt.dz.biz.annotation.MsLog;
import tt.dz.biz.dao.batchpay.BatchPayDAOImp;
import tt.dz.biz.dao.common.CommonDAO;
import tt.dz.biz.dao.merch.ChangeDayDAOImp;
import tt.dz.biz.dao.trade.TradeDAOImpl;
import tt.dz.biz.service.client.OSClientService;
import tt.dz.biz.service.common.CommonService;
import tt.dz.common.BusinessException;
import tt.dz.common.DZStringUtil;
import tt.dz.common.DateUtil;
import tt.dz.common.DzConstants;
import tt.dz.common.DzConstants.BizType;
import tt.dz.common.DzConstants.accountingState;
import tt.dz.common.DzConstants.payState;
import tt.dz.common.DzConstants.userType;
import tt.dz.common.DzErrorCode;
import tt.dz.common.DzErrorCode.CommonErrorCode;
import tt.dz.common.DzErrorCode.TranErrorCode;
import tt.dz.common.LogUtil;
import tt.dz.vo.BatchPayVO;
import tt.dz.vo.OrderServiceVO;
import tt.dz.vo.TranInfoVO;

@Service("batchPayService")
public class BatchPayService
{
  private static final String SEPERATOR = ",";
  @Resource(name="commonService")
  private CommonService commonService;
  @Resource(name="liabilitiesService")
  private LiabilitiesService liabilitiesService;
  @Resource(name="batchPayDAO")
  private BatchPayDAOImp batchPayDAO;
  @Resource(name="changeDayDAO")
  private ChangeDayDAOImp changeDayDAO;
  @Resource(name="commonDAO")
  private CommonDAO commonDAO;
  @Resource(name="tradeDAO")
  private TradeDAOImpl tradeDAO;
  @Resource(name="osClientService")
  private OSClientService osClientService;
  
  @MsLog(bizCode="batchpayJob", bizName="统付数据生成JOB", bizType=DzConstants.BizType.JOB)
  public void saveBatchPayJOB()
    throws Exception
  {
    try
    {
    	Date  endTime = getFirstDayOfMonth();
      List<String> payerList = this.batchPayDAO.queryBatchPayPayerSel(endTime);
      for (String payer : payerList) {
        saveBatchPay(payer, endTime);
      }
    }
    catch (Exception e)
    {
      Date endTime;
      LogUtil.error("生成统付批次异常", e);
      throw e;
    }
  }
  
  private Date getFirstDayOfMonth()
  {
    Date nowDate = this.changeDayDAO.queryAccountingDateForChangeDay();
    return DateUtil.getFirstDayOfMonth(nowDate);
  }
  
  public Map<String, String> queryPayerSelMap(Date endTime)
    throws Exception
  {
    Map<String, String> result = new HashMap();
    List<String> payerList = this.batchPayDAO.queryBatchPayerForWaitForPay();
    for (String payer : payerList)
    {
      String merchantName = this.batchPayDAO.queryMerchantName(payer);
      if (!StringUtils.isBlank(merchantName)) {
        result.put(payer, merchantName);
      }
    }
    return result;
  }
  
  public List<BatchPayVO> queryBatchPay(Map<String, Object> parameter)
    throws Exception
  {
    return this.batchPayDAO.queryBatchPay(parameter);
  }
  
  @MsLog(bizCode="saveBatchPay", bizName="保存统付数据", bizType=DzConstants.BizType.BUSINESS)
  public int[] saveBatchPay(String payer, Date endTime)
    throws Exception
  {
    List<BatchPayVO> batchPayList = new ArrayList();
    List<TranInfoVO> updateTranInfoList = new ArrayList();
    List<Map<String, Object>> tranInfoList = this.batchPayDAO.getTranInfoByPayer(payer, endTime);
    BatchPayVO batchPayVo = null;
    TranInfoVO tranInfoVo = null;
    Integer batchNo = null;
    String receiver = null;
    String serviceNo = null;
    Date nowDate = this.changeDayDAO.queryAccountingDateForChangeDay();
    Calendar calendar = Calendar.getInstance();
    calendar.setTime(nowDate);
    calendar.add(2, -1);
    String batchMonth = new SimpleDateFormat("yyyyMM").format(calendar.getTime());
    Date firstDayOfMonth = getFirstDayOfMonth();
    for (Map<String, Object> tranInfo : tranInfoList)
    {
      receiver = (String)tranInfo.get("receiver");
      serviceNo = (String)tranInfo.get("serviceNo");
      batchNo = this.batchPayDAO.getMaxBatchNo(payer, receiver, serviceNo);
      Integer localInteger1 = batchNo;Integer localInteger2 = batchNo = Integer.valueOf(batchNo.intValue() + 1);
      tranInfoVo = new TranInfoVO();
      batchPayVo = new BatchPayVO();
      batchPayVo.setBatchNo(batchNo);
      batchPayVo.setPayer((String)tranInfo.get("payer"));
      batchPayVo.setReceiver(receiver);
      batchPayVo.setServiceNo(serviceNo);
      Long _totalCount = (Long)tranInfo.get("totalCount");
      BigDecimal _totalFee = (BigDecimal)tranInfo.get("totalAmount");
      batchPayVo.setTotalCount(Integer.valueOf(_totalCount != null ? _totalCount.intValue() : 0));
      batchPayVo.setTotalFee(_totalFee);
      batchPayVo.setState(DzConstants.payState.WAITING_FOR_PAYING.value());
      batchPayVo.setCreatedTime(this.commonService.getDBCurrentTime());
      batchPayVo.setBatchMonth(batchMonth);
      batchPayVo.setAccountingDate(this.changeDayDAO.queryAccountingDateForChangeDay());
      batchPayList.add(batchPayVo);
      tranInfoVo.setBatchNo(batchNo);
      tranInfoVo.setPayer(payer);
      tranInfoVo.setReceiver(receiver);
      tranInfoVo.setAccountingDate(firstDayOfMonth);
      updateTranInfoList.add(tranInfoVo);
    }
    int[] result = this.batchPayDAO.insertBatchBatchPay(batchPayList);
    this.batchPayDAO.updateTranInfoByPayer(updateTranInfoList);
    return result;
  }
  
  public List<OrderServiceVO> querySettlementServiceForBatchPay(String serviceNo)
    throws Exception
  {
    try
    {
      return this.batchPayDAO.querySettlementServiceForBatchPay(serviceNo);
    }
    catch (Exception e)
    {
      LogUtil.error("根据主服务编码查询对应的结算服务列表异常，参数serviceNo：" + serviceNo, e);
      throw e;
    }
  }
  
  @MsLog(bizCode="saveReceivable", bizName="结算应收账款", bizType=DzConstants.BizType.BUSINESS)
  public void saveReceivable(BatchPayVO batchPayVO, TranInfoVO tranInfo)
    throws Exception
  {
    try
    {
      String currentDate = DateUtil.getDateFormatter();
      String seqNo = DZStringUtil.getFixedLengthString(8, String.valueOf(this.tradeDAO.querySequence("seq_trade_no")));
      String tradeNo = String.valueOf(DzConstants.userType.MERCHANT_CUSTOMER.value()) + tranInfo.getAppId() + currentDate + seqNo;
      
      List<String> orderNoList = this.batchPayDAO.queryOrderNoForPaying(batchPayVO);
      
      batchPayVO.setState(DzConstants.payState.PAY_SUCCESS.value());
      batchPayVO.setPayAccountDate(this.commonService.getAccountingDate());
      batchPayVO.setTradeNo(tradeNo);
      int n = this.batchPayDAO.updateReceivableForBatchPay(batchPayVO);
      if (n != 1) {
        throw new BusinessException(DzErrorCode.CommonErrorCode.SAVE_ERROR.value(), "更新收到应收款信息失败。参数batchPayVO为：" + batchPayVO.toString(), "更新收到应收款信息失败。参数batchPayVO为：" + batchPayVO.toString());
      }
      tranInfo.setTradeNo(tradeNo);
      tranInfo.setAccountingDate(this.commonService.getAccountingDate());
      tranInfo.setPlatTime(this.commonService.getDBCurrentTime());
      tranInfo.setAccountState(DzConstants.accountingState.WAIT_FOR_ACCOUNTING.value());
      n = this.tradeDAO.insertTranInfo(tranInfo);
      if (n != 1) {
        throw new BusinessException(DzErrorCode.TranErrorCode.SAVE_TRAN_INFO_FAIL.value(), "保存结算交易信息失败", "保存结算交易信息失败");
      }
      TranInfoVO updateTranInfo = new TranInfoVO();
      updateTranInfo.setPayer(batchPayVO.getPayer());
      updateTranInfo.setReceiver(batchPayVO.getReceiver());
      updateTranInfo.setBatchNo(batchPayVO.getBatchNo());
      updateTranInfo.setPayStateCode(DzConstants.payState.PAY_SUCCESS.value());
      updateTranInfo.setServiceNo(batchPayVO.getServiceNo());
      n = this.tradeDAO.updateBatchPayed(updateTranInfo);
      if (n != batchPayVO.getTotalCount().intValue()) {
        throw new Exception("更新统付或企业支付的交易为已支付时失败，支付批次中笔数为:" + batchPayVO.getTotalCount() + ",更新到的交易记录条数为：" + n + "。参数updateTranInfo为：" + updateTranInfo.toString());
      }
      try
      {
        String orderNos = StringUtils.join(orderNoList, ",");
        
        this.osClientService.unifyAndCorpPay(orderNos);
      }
      catch (Exception e)
      {
        LogUtil.error("修改订单系统的统付和企业支付订单支付状态失败！！！", e);
      }
    }
    catch (Exception e)
    {
      LogUtil.error("保存收到应收账款和插入收到应收账款交易异常，参数batchPayVO：" + batchPayVO + ",tranInfo：" + tranInfo, e);
      throw e;
    }
  }
}
